package com.yiduo.outpost.core.web.argument;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.CaseFormat;
import org.springframework.core.MethodParameter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author yanwen
 */
public class QueryWrapperArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String PARAM_SORT = "sort";
    private static final String PARAM_DIRECTION = "order";
    private static final String PARAM_FILTERING = "filtering";

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return Wrapper.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    public Wrapper<?> resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer,
                                      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws UnsupportedEncodingException {

        List<FilteringParam> params = new ArrayList<>();
        String parameter = webRequest.getParameter(PARAM_FILTERING);
        // filtering字段转成QueryWrapper
        if (StringUtils.hasText(parameter)) {
            params.addAll(JSON.parseArray(QueryWrapperUrlDecoder.decode(parameter, "UTF-8"), FilteringParam.class));
        }
        QueryWrapperDecorators.decorateParams(params, methodParameter.getParameterAnnotation(QueryWrapperDecorator.class));

        QueryWrapper<?> queryWrapper = params.isEmpty() ? new QueryWrapper<>() : FilteringParam.toQueryWrapper(params);

        // 解析排序字段
        String sortParameter = webRequest.getParameter(PARAM_SORT);
        if (StringUtils.isEmpty(sortParameter)) {
            return queryWrapper;
        }

        List<String> sorts = Arrays.stream(sortParameter.split(","))
                .map(s -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, s))
                .collect(Collectors.toList());

        // 解析排序顺序
        Direction.valueOf(
                        Optional.ofNullable(webRequest.getParameter(PARAM_DIRECTION)).orElse(Direction.desc.name()))
                .setSortProperties(queryWrapper, sorts);

        return queryWrapper;
    }

}
